package com.tt.task;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

@Slf4j
@Component
public class MethodTaskScheduler {
    private static final Logger logger = LoggerFactory.getLogger(MethodTaskScheduler.class);
    public final Map<String, ScheduledFuture<?>> taskMaps = new ConcurrentHashMap<>();
    private final TaskExecutionListener taskExecutionListener;
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;


    public MethodTaskScheduler(TaskExecutionListener taskExecutionListener) {
        this.taskExecutionListener = taskExecutionListener;
    }

    /**
     * 调度方法执行任务
     * @param taskId 任务ID
     * @param taskInfo 方法调用信息
     * @param cronExpression cron表达式
     * @return 是否调度成功
     */
    public boolean scheduleMethod(String taskId, MethodTaskInfo taskInfo, String cronExpression) {
        try {
            if (taskMaps.containsKey(taskId)) {
                logger.warn("Task {} already exists, will reschedule it", taskId);
                cancelTask(taskId);
            }

            Runnable task = new MethodInvocationTask(taskInfo,taskExecutionListener);
            ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(
                    task,
                    new CronTrigger(cronExpression)
            );

            taskMaps.put(taskId, future);
            logger.info("Scheduled task {} with cron {}", taskId, cronExpression);
            return true;
        } catch (Exception e) {
            logger.error("Failed to schedule task {}", taskId, e);
            return false;
        }
    }

    /**
     * 取消任务
     * @param taskId 任务ID
     * @return 是否取消成功
     */
    public boolean cancelTask(String taskId) {
        ScheduledFuture<?> future = taskMaps.remove(taskId);
        if (future != null) {
            boolean cancelled = future.cancel(true);
            if (cancelled) {
                logger.info("Cancelled task {}", taskId);
            } else {
                logger.warn("Failed to cancel task {}", taskId);
            }
            return cancelled;
        }
        logger.warn("Task {} not found for cancellation", taskId);
        return false;
    }

    /**
     * 重新调度任务
     * @param taskId 任务ID
     * @param newTaskInfo 新任务信息
     * @param newCron 新cron表达式
     * @return 是否重新调度成功
     */
    public boolean rescheduleMethod(String taskId, MethodTaskInfo newTaskInfo, String newCron) {
        cancelTask(taskId);
        return scheduleMethod(taskId, newTaskInfo, newCron);
    }

    /**
     * 获取任务状态
     * @param taskId 任务ID
     * @return 任务状态信息
     */
    public TaskStatus getTaskStatus(String taskId) {
        ScheduledFuture<?> future = taskMaps.get(taskId);
        if (future == null) {
            return TaskStatus.NOT_EXISTS;
        }
        if (future.isCancelled()) {
            return TaskStatus.CANCELLED;
        }
        if (future.isDone()) {
            return TaskStatus.COMPLETED;
        }
        return TaskStatus.RUNNING;
    }

    /**
     * 获取所有任务信息
     * @return 任务映射表(不可修改的副本)
     */
    public Map<String, ScheduledFuture<?>> getAllTasks() {
        return Collections.unmodifiableMap(new HashMap<>(taskMaps));
    }


    public enum TaskStatus {
        NOT_EXISTS, RUNNING, CANCELLED, COMPLETED
    }

    public Map<String, ScheduledFuture<?>> getTaskMaps() {
        return taskMaps;
    }
}
